<script lang="tsx">
import {
  defineComponent,
  ref,
  computed,
  type PropType,
  type ExtractPropTypes,
  provide,
  reactive,
  getCurrentInstance,
  watch
} from 'vue'
import { ElDialog } from 'element-plus'
import { merge } from 'lodash-es'
import { getValOrFnResult, type SimpleKeyValueObject } from '../form/utils'
import oFormFactory, {
  oFormProps,
  type iFormColumnType
} from '../form/factory.vue'
import { isPromise, isAsync } from '../utils'
export interface iDialogOptionsProps {
  columns: Array<iFormColumnType>
  title?: string
  [key: string]: string | number | boolean | Array<iFormColumnType> | undefined
}
export const oDialogProps = {
  setup: Function,
  dialogOptions: {
    type: Object as PropType<iDialogOptionsProps>
  },
  header: Function,
  body: Function,
  footer: Function
}
export type oDialogPropsType = ExtractPropTypes<typeof oDialogProps>
export default defineComponent({
  components: { oFormFactory, ElDialog },
  props: oDialogProps,
  setup(props: oDialogPropsType, context) {
    const refFormFactory = ref()
    const formData = reactive({} as SimpleKeyValueObject)
    provide('formData', formData)
    provide('eventData', {})
    let setupResult = props.setup?.(props, context)
    if (isPromise(setupResult) || isAsync(setupResult)) {
      throw new Error('弹窗hook不能是异步，请在oDialog.open外部写异步初始化')
    }
    const dialogOptionsSync = computed(() => {
      const obj = merge(
        {
          validate: true, // 开启表单验证
          title: '',
          columns: [] as Array<iFormColumnType>
        },
        setupResult.dialogOptions
      )
      obj.title = getValOrFnResult(obj.title)
      obj.columns.forEach((colItem: iFormColumnType) => {
        colItem.type = 'primary'
        colItem.size = 'small'
      })
      return obj
    })

    // const ins = getCurrentInstance() // {ctx} this对象
    let dialogVisible = ref(true)

    context.expose({
      // 主动触发校验
      validate(fields: Array<string> = []) {
        refFormFactory?.value.onValidate(
          setupResult.onSubmit,
          setupResult.onValidError,
          fields
        )
      },
      // 清空验证
      clearValidate(fields: Array<string> = []) {
        refFormFactory?.value.clearValidate(fields)
      }
    })
    // 关闭时触发销毁
    watch(dialogVisible, () => {
      if (!dialogVisible.value) {
        context.emit('unmounted')
      }
    })
    const footerOptionsSync = computed(() => {
      return {
        inline: true,
        columns: [
          {
            labelWidth: 0,
            comtype: 'button',
            label: '确定',
            type: 'primary',
            onClick() {
              // 触发表单验证，onSubmit成功回调，onValidError失败回调
              refFormFactory?.value.onValidate(
                setupResult.onSubmit,
                setupResult.onValidError
              )
            }
          },
          {
            labelWidth: 0,
            comtype: 'button',
            label: '取消',
            onClick() {
              const v = setupResult.onCancel?.(formData)
              if (v !== false) {
                dialogVisible.value = false
              }
            }
          }
        ]
      }
    })
    const onClose = () => {
      // 点击确定后，没返回false，就关闭
      dialogVisible.value = false
    }
    return () => (
      <ElDialog
        class="one-dialog"
        {...dialogOptionsSync.value}
        destroy-on-close
        v-model={dialogVisible.value}
        v-slots={{
          header: () => {
            return props.header ? (
              props.header()
            ) : (
              <div>{dialogOptionsSync.value.title}</div>
            )
          },
          default: () => {
            return props.body ? (
              props.body()
            ) : (
              <oFormFactory
                ref={refFormFactory}
                formOptions={dialogOptionsSync}
                onClose={onClose}
              />
            )
          },
          footer: () => {
            return props.footer ? (
              props.footer()
            ) : (
              <oFormFactory formOptions={footerOptionsSync} />
            )
          }
        }}
      ></ElDialog>
    )
  }
})
</script>

<style lang="scss">
.one-dialog {
  .el-dialog__footer {
    .one-form {
      display: flex;
      justify-content: center;
      padding-right: 0;
    }
  }
}
</style>
